﻿#region 命名空间

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Sharp.Domain.PlatformBoundedContext.PermissionModule.Aggregates;
using Sharp.Domain.PlatformBoundedContext.UserModule.Aggregates;
using Sharp.Domain.Repositories;
using Sharp.Domain.Repository.EF;
using Sharp.Infrastructure;

#endregion

namespace Sharp.Domain.PlatformBoundedContext.UserModule.Services
{
    /// <summary>
    ///     表示用于Sharp领域模型中的领域服务类型。
    /// </summary>
    public partial class UserService : IUserService
    {
        #region 私有字段

        private readonly IPermissionRepository _permissionRepository;
        private readonly IRepositoryContext _repositoryContext;
        private readonly IRoleRepository _roleRepository;
        private readonly IUserGroupRepository _userGroupRepository;
        private readonly IUserRepository _userRepository;

        #endregion

        #region 构造函数

        /// <summary>
        ///     初始化一个新的<c>UserService</c>类型的实例。
        /// </summary>
        /// <param name="repositoryContext">仓储上下文。</param>
        /// <param name="userRepository">用户仓储。</param>
        /// <param name="userGroupRepository">用户组仓储</param>
        /// <param name="permissionRepository">权限仓储</param>
        /// <param name="roleRepository">角色仓储。</param>
        public UserService(IRepositoryContext repositoryContext,
            IUserRepository userRepository,
            IUserGroupRepository userGroupRepository,
            IPermissionRepository permissionRepository,
            IRoleRepository roleRepository)
        {
            _repositoryContext = repositoryContext;
            _userRepository = userRepository;
            _userGroupRepository = userGroupRepository;
            _permissionRepository = permissionRepository;
            _roleRepository = roleRepository;
        }

        #endregion

        #region 用户

        /// <summary>
        /// 用户名是否存在
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public bool UserNameExists(string userName)
        {
            return _userRepository.Exists(x => x.UserName == userName);
        }
        /// <summary>
        /// 电邮是否已注册
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        public bool EmailExists(string email)
        {
            return _userRepository.Exists(x => x.Email == email);
        }
        /// <summary>
        /// 检查密码
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public bool CheckPassword(string userName, string password)
        {
            return _userRepository.Exists(x => x.UserName == userName && x.Password == password);
        }
        /// <summary>
        /// 通过用户名获取用户信息
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public User GetUserByName(string userName)
        {
            (this._repositoryContext as EntityFrameworkRepositoryContext).Context.Configuration.LazyLoadingEnabled = false;
            var user = _userRepository.Get(x => x.UserName == userName, x => x.Person, x => x.Permissions);


            return user;
        }
        /// <summary>
        /// 通过电邮获取用户信息
        /// </summary>
        /// <param name="email"></param>
        /// <returns></returns>
        public User GetUserByEmail(string email)
        {
            return _userRepository.Get(x => x.Email == email);
        }

        #region 记录登录信息
        /// <summary>
        /// 记录登录信息
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public Result<User> TryLogin(User user)
        {
            var res = new Result<User>();
            if (ContactContext.Current.SystemCode.IsNullOrEmpty())
            {
                res.Err = "SystemCode属性必须赋值";
                return res;
            }

            (this._repositoryContext as EntityFrameworkRepositoryContext).Context.Configuration.LazyLoadingEnabled = false;
            var info = _userRepository.Get(x => x.UserName == user.UserName);
            if (info == null)
            {
                res.Err = "用户不存在。";
                return res;
            }
            if (!user.Password.Md5().Equals(info.Password, StringComparison.CurrentCultureIgnoreCase))
            {
                res.Err = "密码错误。";
                return res;
            }

            info.LastLogonTime = DateTime.Now;
            info.LastLogonIp = user.LastLogonIp;

            _userRepository.Update(info);

            _userRepository.Context.Commit();


            var permissions = _permissionRepository.GetList(x => x.SystemCode == user.SystemCode && x.Users.Any(y => y.Id == info.Id));
            info.Permissions = permissions;

            res.Id = info.Id;
            res.Data = info;
            return res;
        }
        #endregion


        public IEnumerable<Permission> GetPermissionByUserName(string username)
        {
            var permissions = _permissionRepository.GetList(x => x.Users.Any(y => y.UserName == username));
            return permissions.Where(x => x.SystemCode ==
            ContactContext.Current.SystemCode || ContactContext.Current.SystemCode.IsNullOrEmpty());
        }
        public IEnumerable<Permission> GetPermissionById(Guid id)
        {
            return _userRepository.Get(x => x.Id == id, x => x.Permissions).Permissions.ToList();
        }
        #endregion

        #region 保存权限
        /// <summary>
        ///     保存权限
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="owner"></param>
        /// <param name="ownerId"></param>
        public Result SavePermission(IList<Guid> ids, string owner, Guid ownerId)
        {
            var res = new Result();
            if (ContactContext.Current.SystemCode.IsNullOrEmpty())
            {
                res.Err = "SystemCode为初始化。";
                return res;
            }
            if (owner == "user")
            {
                var user = _userRepository.Get(ownerId, x => x.Permissions);
                if (user.Permissions.Any())
                {
                    user.Permissions.ToList().RemoveAll(x => x.SystemCode== ContactContext.Current.SystemCode);
                }
                ids.ToList().ForEach(x => user.Permissions.Add(_permissionRepository.Get(x)));

                _repositoryContext.Commit();
            }
            else
            {
                var userGroup = _userGroupRepository.Get(ownerId);
                if (userGroup.Permissions.Any())
                {
                    userGroup.Permissions.ToList().RemoveAll(x => x.SystemCode == ContactContext.Current.SystemCode);
                }
                ids.ToList().ForEach(x => userGroup.Permissions.Add(_permissionRepository.Get(x)));

                _repositoryContext.Commit();
            }
            return res;
        }
        #endregion

        #region 将指定的用户赋予特定的角色。
        /// <summary>
        ///     将指定的用户赋予特定的角色。
        /// </summary>
        /// <param name="user">用户实体。</param>
        /// <param name="role">角色实体。</param>
        /// <returns>用以表述用户及其角色之间关系的实体。</returns>
        public User AssignRole(User user, Role role)
        {
            if (user == null)
                throw new ArgumentNullException("user");
            if (role == null)
                throw new ArgumentNullException("role");

            Expression<Func<User, bool>> specExpression = null;
            if (role == null)
                specExpression = ur => ur.Id == user.Id;
            else
                specExpression = ur => ur.Id == user.Id && ur.Roles.Any(x => x.Id == role.Id);

            var info = _userRepository.Get(specExpression);
            if (info != null)
            {
                info.Roles.Add(role);
                _repositoryContext.Commit();
            }

            return user;
        }
        #endregion

        #region 将指定的用户从角色中移除。
        /// <summary>
        ///     将指定的用户从角色中移除。
        /// </summary>
        /// <param name="user">用户实体。</param>
        /// <param name="role">角色实体，若为NULL，则表示从所有角色中移除。</param>
        public void UnassignRole(User user, Role role = null)
        {
            if (user == null)
                throw new ArgumentNullException("user");
            Expression<Func<User, bool>> specExpression = null;
            if (role == null)
                specExpression = ur => ur.Id == user.Id;
            else
                specExpression = ur => ur.Id == user.Id && ur.Roles.Any(x => x.Id == role.Id);

            var info = _userRepository.Get(specExpression);

            if (info != null)
            {
                info.Roles.Remove(role);
                _repositoryContext.Commit();
            }
        }
        #endregion

        #region 关联用户到用户组
        /// <summary>
        /// 关联用户到用户组
        /// </summary>
        /// <param name="userGroupId">用户组Id</param>
        /// <param name="userIds">用户Id</param>
        /// <returns></returns>
        public Result RelationUser(Guid userGroupId, Guid[] userIds)
        {
            Result res = new Result();
            (_userGroupRepository.Context as EntityFrameworkRepositoryContext).Context.Configuration
                    .LazyLoadingEnabled = true;

            var userGroup = _userGroupRepository.Get(x => x.Id == userGroupId);
            if (userGroup == null)
            {
                res.Err = "用户组不存在。";
                return res;
            }

            _userRepository.GetList(x => userIds.Contains(x.Id)).ToList().ForEach(u =>
            {
                //新用户增加用户组的权限
                u.Permissions = u.Permissions.Union(userGroup.Permissions).ToList();

                userGroup.Users.Add(u);
            });



            return res;
        }
        #endregion

        #region 反关联用户组的用户
        /// <summary>
        /// 反关联用户组的用户
        /// </summary>
        /// <param name="userGroupId">用户组Id</param>
        /// <param name="userIds">用户Id</param>
        /// <returns></returns>
        public Result UnRelationUser(Guid userGroupId, Guid[] userIds)
        {
            Result res = new Result();
            (_userGroupRepository.Context as EntityFrameworkRepositoryContext).Context.Configuration
                    .LazyLoadingEnabled = true;
            var userGroup = _userGroupRepository.Get(x => x.Id == userGroupId);
            if (userGroup == null)
            {
                res.Err = "用户组不存在。";
                return res;
            }

            userGroup.Users.Where(x => userIds.Contains(x.Id)).ToList().ForEach(u =>
            {
                //移除用户的权限
                userGroup.Permissions.ToList().ForEach(p =>
                {
                    u.Permissions.Remove(p);
                });

                userGroup.Users.Remove(u);
            });

            return res;
        }
        #endregion

        /// <summary>
        /// 有权限的组织的数据
        /// </summary>
        /// <returns></returns>
        public List<Guid> GetAuthorizedOrgIds()
        {
            (this._repositoryContext as EntityFrameworkRepositoryContext).Context.Configuration.ProxyCreationEnabled = true;
            var user = _userRepository.Get(ContactContext.Current.UserId);
            var orgIds = user.AuthorizedOrgs.Select(x => x.Id).ToList();
            if (!orgIds.Any())
            {
                if (ContactContext.Current.OrgId.HasValue)
                    return new List<Guid>() { ContactContext.Current.OrgId.Value };
                else return new List<Guid>();
            }
            return orgIds;
        }
    }
}